<?php

namespace App\Jobs;


use App\Models\Order\Outboundorder;
use App\Models\Order\Outboundordersub;
use App\Models\Order\Saleorderfee;
use App\Models\Order\Saleordersub;
use App\Models\Order\Salesorder;
use App\Models\Order\Salesordersub;
use App\Models\SaleCover\SaleCover;
use App\Services\SaleOrder\SaleOrder;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels;
use Illuminate\Support\Facades\Log;
use mysql_xdevapi\Exception;

class SaleCoverJob implements ShouldQueue
{
    use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;


    /**
     * 销售定价一键覆盖
     */
    const QUEUE_JOB = 'sale-cover-job';

    public $data;
    public $tries = 3;      // Laravel 自动重试次数（包括首次执行）
    public $timeout = 60;

    public $mangerinfo = [];

    public function __construct($data, $mangerinfo = [])
    {
        $this->data = $data;
        $this->mangerinfo = $mangerinfo;
    }

    public function handle()
    {
        $id = $this->data['id'];
        $mangerinfo = $this->mangerinfo;
        $cpid = $mangerinfo['cpid'] ?? 0;

        $cover = SaleCover::query()->where(['id' => $id, 'is_del' => 1, 'cpid' => $cpid])->first();

        try {
            // 参数校验
            if (!empty($cover)) {

                $cover = $cover->toArray();

                $type = $cover['type'];

                if ($type == 1) {
                    $startAt = strtotime(date('Y-m-d 00:00:00'));
                    $edAt = strtotime(date('Y-m-d 23:59:59'));
                } else {
                    $startAt = $cover['start_time'];
                    $edAt = $cover['end_time'];
                }

                $saleprice = (new SaleOrder())->getsaleprice($mangerinfo);

                $basePrice = $saleprice['base']['基价']['amount'] ?? 0;
                $where = [];
                $where[] = ['cpid', '=', $mangerinfo['cpid']];
                $where[] = ['create_at', '>=', $startAt];
                $where[] = ['create_at', '<=', $edAt];
                $where[] = ['is_del', '=', 1];

                // 订单计算金额和计提、业绩
                $this->exeSaleOrder($where, $mangerinfo, $saleprice, $basePrice);
                // 发货单
                $this->exeSalesOrder($where, $mangerinfo, $saleprice, $basePrice);

                //  出库单
                $this->exeOutboundOrder($where, $mangerinfo, $saleprice, $basePrice);

            }

        } catch (\Throwable $e) {
            $this->handleFailure($e);
        }
    }


    /**
     * 销售出库单
     * @param $where
     * @param $mangerinfo
     * @param $saleprice
     * @param $basePrice
     * @return void
     * @throws \Exception
     */
    public function exeSalesOrder($where, $mangerinfo, $saleprice, $basePrice)
    {

        $orderList = Salesorder::query()->with(['suborder' => function ($query) {
            $query->where('is_del', config('constants.is_del.no'));
        }])
            ->where('is_del', config('constants.is_del.no'))
            ->where($where)
            ->get()
            ->toArray();



        $order_number_arr = array_column($orderList, 'order_number');
        $otherPriceArr = $this->getfee($order_number_arr);


        $saleList = \App\Models\Order\Saleorder::query()
            ->whereIn('order_number',$order_number_arr)
            ->get(['id','order_number','extra_type','order_type'])
            ->pluck(null,'order_number')
            ->toArray();

        foreach ($orderList as $order) {

            $order['extra_type'] = $saleList[$order['order_number']]['extra_type']?? 0;
            if (isset($order['suborder']) && !empty($order['suborder'])) {

                foreach ($order['suborder'] as $sub) {

                    $sub['guiding_price'] = $basePrice;
                    // 加价规则，1销售订单日期，2销售订单发货日期
                    if ((int)$order['extra_type'] == 1) {
                        // 基价+加价 =单价
                        $guiding_price = (new SaleOrder())->getsteelprice($saleprice, $basePrice, $sub);
                        $sub['guiding_price'] = $guiding_price;
                    }

                    $sub['salefee'] = $otherPriceArr[$order['order_number']]['other_price_total'] ?? 0;
                    $sub['total_weight'] = $sub['weight'];

                    $sub['node'] = 'sales_order';
                    $res = (new SaleOrder())->getaccrualperformance($sub, $mangerinfo, false);

                    Salesordersub::query()->where('id', $sub['id'])->update([
                        'accrual' => $res['accrual'],
                        'performance' => $res['performance'],
                        'guiding_price' => $sub['guiding_price'],
                    ]);

                }

            }

        }
    }


    /**
     *
     * 销售订单
     * @param $where
     * @param $mangerinfo
     * @param $saleprice
     * @param $basePrice
     * @return void
     * @throws \Exception
     */
    public function exeSaleOrder($where, $mangerinfo, $saleprice, $basePrice)
    {
        $orderList = \App\Models\Order\Saleorder::query()->with(['suborder' => function ($query) {
            $query->where('is_del', config('constants.is_del.no'));
        }])
            ->where($where)
            ->get()
            ->toArray();

        $order_number_arr = array_column($orderList, 'order_number');

        // 计算销售其他费用
        $otherPriceArr = $this->getfee($order_number_arr);

        $saleList = \App\Models\Order\Saleorder::query()
            ->whereIn('order_number',$order_number_arr)
            ->get(['id','order_number','extra_type','order_type'])
            ->pluck(null,'order_number')
            ->toArray();

        foreach ($orderList as $order) {

            $order['extra_type'] = $saleList[$order['order_number']]['extra_type']?? 0;

            if (isset($order['suborder']) && !empty($order['suborder'])) {
                foreach ($order['suborder'] as $sub) {
                    $sub['guiding_price'] = $basePrice;
                    // 加价规则，1销售订单日期，2销售订单发货日期
                    if ((int)$order['extra_type'] == 1) {
                        // 基价+加价 =单价
                        $guiding_price = (new SaleOrder())->getsteelprice($saleprice, $basePrice, $sub);
                        $sub['guiding_price'] = $guiding_price;
                    }

                    $other_price_total = $otherPriceArr[$order['order_number']]['other_price_total'] ?? 0;

                    $sub['salefee'] = $other_price_total;

                    $res = (new SaleOrder())->getaccrualperformance($sub, $mangerinfo, false);

                    Saleordersub::query()->where('id', $sub['id'])->update([
                        'accrual' => $res['accrual'],
                        'performance' => $res['performance'],
                        'guiding_price' => $sub['guiding_price'],
                    ]);

                }
            }

        }
    }


    /**
     * 销售出库单
     * @param $where
     * @param $mangerinfo
     * @param $saleprice
     * @param $basePrice
     * @return void
     * @throws \Exception
     */
    public function exeOutboundOrder($where, $mangerinfo, $saleprice, $basePrice)
    {
        unset($where[3]);
        $outList = Outboundorder::query()->with(['suborder' => function ($query) {
            $query->where('return_status', '!=', config('constants.return_goods_status.pass'));

        }])
            ->where($where)
            ->get()
            ->toArray();

        $order_number_arr = array_column($outList, 'order_number');

        // 计算销售其他费用
        $otherPriceArr = $this->getfee($order_number_arr);

        $saleList = \App\Models\Order\Saleorder::query()
            ->whereIn('order_number',$order_number_arr)
            ->get(['id','order_number','extra_type','order_type'])
            ->pluck(null,'order_number')
            ->toArray();


        foreach ($outList as $order) {

            $order['extra_type'] = $saleList[$order['order_number']]['extra_type']?? 0;

            if (isset($order['suborder']) && !empty($order['suborder'])) {

                foreach ($order['suborder'] as $sub) {
                    $sub['guiding_price'] = $basePrice?? 0;
                    // 加价规则，1销售订单日期，2销售订单发货日期
                    if ((int)$order['extra_type'] == 1) {
                        // 基价+加价 =指导价
                        $guiding_price = (new SaleOrder())->getsteelprice($saleprice, $basePrice, $sub);
                        $sub['guiding_price'] = $guiding_price;
                    }

                    $sub['salefee'] = $otherPriceArr[$order['order_number']]['other_price_total'] ?? 0;
                    $sub['total_weight'] = $sub['weight'];
                    $res = (new SaleOrder())->getaccrualperformance($sub, $mangerinfo, false);

                    Outboundordersub::query()->where('id', $sub['id'])->update([
                        'accrual' => $res['accrual'],
                        'performance' => $res['performance'],
                        'guiding_price' => $sub['guiding_price'],
                    ]);

                }
            }

        }

    }


    public function getfee($order_number_arr)
    {
        return Saleorderfee::query()
            ->whereIn('order_number', $order_number_arr)
            ->where('is_del', 1)
            ->selectRaw("SUM(price) as other_price_total,order_number")
            ->groupBy('order_number')
            ->get()
            ->pluck(null, 'order_number')
            ->toArray();

    }


    protected function handleFailure(\Throwable $e)
    {
        // 参数错误立即失败，不重试
        if ($e instanceof \InvalidArgumentException) {
            $this->failed($e);
            return;
        }

        // 可重试错误：达到最大尝试次数后标记失败
        if ($e instanceof \RuntimeException) {
            if ($this->attempts() >= $this->tries) {
                $this->failed($e);
            } else {
                throw $e;
            }
        }
    }

    public function failed(\Throwable $exception)
    {
        Log::info($exception->getMessage() . 'failed方法');
        $this->data["error"] = $exception->getMessage();
        $this->data["res"] = "销售定价,同步失败";
        Log::info($exception->getMessage());
        return;
    }
}
